/*
 * Description: 应用时长打点
 */
#ifndef APP_USING_REPORT_H
#define APP_USING_REPORT_H
#include "process_load_statistic/sys_cpu_calc.h"
#include <Windows.h>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <map>
#include <thread>
#include <sstream>
#include "singleton.h"
#include "process_detect.h"
#include "rpc_service/sendto_host.h"

namespace DFX {

struct ApplicationInfo {
    // 应用名称
    std::wstring appName = L"";
    // 应用版本
    std::string appVersion = "";
    // 应用打开时间
    time_t appLaunchTime = 0;
    // 应用退出时间
    time_t appQuitTime = 0;
    // 应用使用内存
    int appMemory = 0;
    // 应用占用提交内存大小
    int appPageFile = 0;
    // 应用占用cpu情况
    float appCpuRate = 0.0f;
    // 磁盘写速率
    float appDiskReadSpeepd = 0.0f;
    // 磁盘写速率
    float appDiskWriteSpeepd = 0.0f;
    // 当前应用是否处于前台
    bool appIsFocused = false;
    // 应用是否处于全屏状态
    bool appIsFullScreen = false;
    // 应用是否填满屏幕除任务栏外所有区域
    bool appIsSemiFullScreen = false;
};

struct SystemInfo {
    // 开机占用内存大小
    int bootMemory = 0;
    // 开机时长
    float bootTime = 0.0f;
    // cpu使用率
    float cpuUsage = 0.0f;
    // 内存使用率
    int memoryUsage = 0;
    // cpu温度
    int cpuTemp = 0;
    // 是否接入电源
    int isPowerConn = 0;
    // 剩余电量
    int batteryRemains = 0;
    // 碎片文件大小
    int fragileFilesSize = 0;
    // 注册表大小
    int regFilesSize = 0;
    // 内存空闲率
    int memoryFreeRate = 0;
    // 磁盘使用率
    float diskUsageRate = 0;
    // 磁盘IO速率
    long long totalIoSpeed = 0;
    // 句柄数量
    size_t handleNum = 0;
    // 进程数量
    size_t processNum = 0;
    // 线程数量
    size_t threadNum = 0;
    // 文件系统缓存大小
    long fileSystemCache = 0;
    // 系统响应度队列
    std::string responseInfo = "";
    // CPU功耗
    double cpuPower = 0.0f;
    // CPU频率
    double cpuSpeed = 0.0f;
    // CPU最大频率
    double cpuMaxSpeed = 0.0f;
    // 当前时间, UTC秒数
    time_t currentTime = 0;
    // 当前时间,字符串格式
    std::string currentTimeString = "";
    // 网络接入状态：有线、无线、离线
    int mode = 0;
    // soc ntc温度
    float socNtcTemp = 0.0f;
    // cpu频率
    float cpuFreq = 0.0f;
    // 单个核心CPU的使用率
    std::vector<double> vecCpuCoreUsage = {};
    // GPU使用率
    float gpuUsage = 0.0f;
    // 系统可用内存
    DWORDLONG availPhyMem = 0;
    // 系统总内存
    DWORDLONG totalPhyMem = 0;
    // 系统PL1
    float powerLimit = 0.0f;
    // 系统可用提交内存
    DWORDLONG availPageFile = 0;
    // 系统总提交内存
    DWORDLONG totalPageFile = 0;
    // 系统提交内存使用率
    int pageLoad = 0;
};

struct PerfDataContainer {
    std::vector<ApplicationInfo> vecApplicationInfo = {};
    SystemInfo systemInfo;
    std::vector<std::pair<std::string, std::pair<float, std::string>>> vecTopProcCpuUsage = {};
    std::vector<std::pair<std::string, DWORDLONG>> vecTopProcMem = {};
    std::vector<std::pair<std::string, DWORDLONG>> vecTopProcPage = {};
};

class AppUsingReport {
public:
    AppUsingReport() = default;
    ~AppUsingReport() = default;
    void Init(std::shared_ptr<WINCONTROL::SendToHost> sendtoHost);
    void Deinit();
    void Start();
    void Stop();
    void SetShutdownFlag();
private:
    bool GetFileVersion(const std::string& filePath, std::string& fileVersion);
    void FillPerfData(PerfDataContainer& perfData);
    void GetSystemInfo(SystemInfo& systemInfo);
    void ReportPerfData();
    void GetTopProcessCpuInfo(PerfDataContainer &perfData);
    void GetTopProcessMemInfo(PerfDataContainer &perfData, const int topN,
        std::map<DWORD, SystemProcessItem>& processinfo);
    void GetTopProcessPageInfo(PerfDataContainer &perfData, const int topN,
        std::map<DWORD, SystemProcessItem>& processinfo);
    void RecordBiLog(PerfDataContainer &perfData);
    void GetProcessInfo(std::vector<ApplicationInfo>& vecAppInfo);
    void GetReportAppData(const ProcessLifeRecord& procLifeRecord,
        const SystemProcessItem& procInfo, std::vector<ApplicationInfo>& vecAppInfo);
    void GetReportAppDataAfterProcessHaveClosed(const ProcessLifeRecord& procLifeRecord,
        std::vector<ApplicationInfo>& vecAppInfo);
    void FormatAppInfo(const PerfDataContainer &perfData, std::ostringstream& displayPerfDataStream);
    void FormatAppCpuTopN(const std::vector<std::pair<std::string,
        std::pair<float, std::string>>>& cpuTopApp, std::string& outputInfo);
    void AppMemTopN(PerfDataContainer &perfData, std::string& outputInfo);
    void AppPageTopN(PerfDataContainer &perfData, std::string& outputInfo);
    void CollectSysLoadData();
    void MonitorWinEvent();
    void RecvMessage(HANDLE hPipe);
    BOOL GetSecurityAttributes(SECURITY_ATTRIBUTES &sa);
    void SessionChanged(int32_t state);
    bool GetBatteryLifePercent(int& batteryLifePercent);
    double GetSystemDiskUsageRate();
    bool GetPowerOnlineStatus(int& powerStatus);
    std::string GetCurrentTimeWithMilliseconds();
    void GetSystemMemoryInfo(SystemInfo& systemInfo);
    void FormatSystemInfo(const PerfDataContainer &perfData, std::ostringstream& displayPerfDataStream);

    std::string sessionName = "AppUsingReport";
    std::shared_ptr<WINCONTROL::SendToHost> m_sendtoHost{ nullptr };

    std::mutex reportMtx;
    std::condition_variable reportCV;
    std::thread appUsingReportThread;
    bool stopReportFlag = false;

    std::mutex collectMtx;
    std::condition_variable collectCV;
    std::thread sysCpuCalcThread;
    bool stopCollectFlag = false;

    std::thread monitorSysWndThread;
    std::atomic<bool> isWinEvtMonitorConnected = false;
    std::atomic<bool> stopMonitorWndEvtFlag = false;

    HANDLE hPipe = INVALID_HANDLE_VALUE;
    OVERLAPPED connOverLapped;

    std::atomic<bool> isShutDown = false;
};

#define APP_USING_REPORT SingletonNew<DFX::AppUsingReport>::GetInstance()
}  // namespace DFX
#endif